#include <vcl.h>
#pragma hdrstop

#include "CCheckB.h"
#include "CGBox.h"
#include "CEdit.h"
#pragma package(smart_init)


//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//
static inline void ValidCtrCheck(CCheckBox *)
	{
	new CCheckBox(NULL);
	}


namespace Ccheckb
	{
    void __fastcall PACKAGE Register()
        {
        TComponentClass classes[1] = {__classid(CCheckBox)};
        RegisterComponents("EIC Ctrlstd", classes, 0);
        }
    }

//////////////////////////////////////
//
// CCheckBox
//
// Fonction: Constructeur
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
__fastcall CCheckBox::CCheckBox(TComponent* Owner)
	: TCustomControl(Owner)
	{
	FChecked            = false;
	inherited::TabStop  = true;
//    inherited::Color    = clBtnFace;
	bFocused            = false;
	ParentColor         = true;
	bCheckedFromClick	= false;

	Width               = DEFAULT_WIDTH;
	Height              = DEFAULT_HEIGHT;

	BmpCheck            = NULL;
	LCaption            = NULL;
  FReference          = EmptyStr;

	LoadBmpCheck();
	InitCaption();
	}

__fastcall CCheckBox::~CCheckBox()
{
  delete BmpCheck;
}


//////////////////////////////////////
//
// SetAlignment
//
// Fonction: Initialise la position du Radio par / au Caption
//
// P.E.: Alignment
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::SetAlignment( enum TCheckBoxAlign AAlignment )
	{
    FAlignment = AAlignment;
    Repaint();
    }



//////////////////////////////////////
//
// SetCaption
//
// Fonction: Initialise Caption
//
// P.E.: Caption
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::SetCaption( const AnsiString aCaption )
    {
    inherited::Caption = aCaption;
    InitCaption();
    Repaint();
    }



//////////////////////////////////////
//
// SetChecked
//
// Fonction: Initialise Checked
//
// P.E.: Checked
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::SetChecked( bool bChecked )
	{
//	bool Flag = FChecked;

    if( FChecked==bChecked) return;

	FChecked = bChecked;

	if( !bCheckedFromClick )
		{
		if( OnCheck )
			OnCheck( this, Checked );

		inherited::Click();
		}
	bCheckedFromClick = false;
	Repaint();
	}



//////////////////////////////////////
//
// SetEnabled
//
// Fonction: Initialise Enabled
//
// P.E.: Enabled
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::SetEnabled(     bool        bEnabled )
    {
    inherited::Enabled  = bEnabled;
    LCaption->Enabled   = bEnabled;
    Repaint();
    }

//////////////////////////////////////
//
// SetReadOnly
//
// Fonction: Initialise ReadOnly
//
// P.E.: ReadOnly
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::SetReadOnly(    bool        bReadOnly )
    {
    FReadOnly           = bReadOnly;
    inherited::TabStop  = !bReadOnly;
    Repaint();
    }



//////////////////////////////////////
//
// GetCaption
//
// Fonction: Renvoie Caption
//
// P.E.: AUCUN
//
// P.S.: Caption
//
//////////////////////////////////////
AnsiString  __fastcall CCheckBox::GetCaption() /*const*/
    {
    return( inherited::Caption );
    }



//////////////////////////////////////
//
// GetEnabled
//
// Fonction: Renvoie Enabled
//
// P.E.: AUCUN
//
// P.S.: Enabled
//
//////////////////////////////////////
bool __fastcall CCheckBox::GetEnabled()
    {
    return( inherited::Enabled );
    }



//////////////////////////////////////
//
// Paint
//
// Fonction: Redessine le controle
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::Paint()
    {
	int TopOption       = ( Height - BmpCheck->Height ) / 2;
	int	iBord			= 0;

	Canvas->CopyMode    = cmSrcCopy;

	LoadBmpCheck();

	if( Alignment == eChkBxLeftAlign )
		{
		Canvas->Draw( iBord, TopOption, BmpCheck );
		LCaption->Left  = BmpCheck->Width + SIZE_ESP;
		}
	else
		{
        Canvas->Draw( Width - BmpCheck->Width - iBord, TopOption, BmpCheck );
        LCaption->Left  = 2;
        }

    LCaption->Top       = ( Height - LCaption->Height ) / 2;

    LCaption->Font->Assign( Font );
    LCaption->Caption   = Caption;
    if( LCaption->Height > Height - 4 )
        Height          = LCaption->Height + 4;
    if( LCaption->Width > Width )
		Width           = LCaption->Width + BmpCheck->Width + SIZE_ESP + 20;

    DrawContour( bFocused );
    }



//////////////////////////////////////
//
// DrawContour
//
// Fonction: Dessine un cadre autour du Caption lorsque le
//           controle recoit la focalisation
//
// P.E.: Contour visible / non visible
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::DrawContour( bool bVisible )
	{
	int     i       = LCaption->Left  - 1;
	int     j       = LCaption->Top   - 1;
	int		iLeft;
	int		iTop;
	int		iWidth;
	int		iHeight;
	TColor  CColor;

	if( bVisible )
		CColor 	= clBlack;
	else
		CColor 	= Color;

	if(( LCaption && LCaption->Caption.IsEmpty()))
		{
		iLeft	= 1;
		iTop	= 2;
		iWidth	= BmpCheck->Width - 1;
		iHeight	= BmpCheck->Height;
		}
	else
		{
		iLeft	= LCaption->Left;
		iTop	= LCaption->Top;
		iWidth	= LCaption->Width;
		iHeight	= LCaption->Height;
		}

	i 			= iLeft - 1;
	j 			= iTop 	- 1;

	while( i < iLeft + iWidth + 1 )
		{
		Canvas->Pixels[i][iTop - 1]                  		= CColor;
		Canvas->Pixels[i][iTop + iHeight]   				= CColor;
		i += 2;
		}

	while( j < iTop + iHeight + 1 )
		{
		Canvas->Pixels[iLeft - 1][j]                 		= CColor;
		Canvas->Pixels[iLeft + iWidth + 1][j] 				= CColor;
		j += 2;
		}
	}



//////////////////////////////////////
//
// LoadBmpCheck
//
// Fonction: Charge le Bmp correspondant a l'etat du check
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::LoadBmpCheck()
    {
    AnsiString aEtat;
    enum StateChkBx eState;


    if( BmpCheck )
        {
        delete BmpCheck;
        BmpCheck = NULL;
        }

    try
        {
        BmpCheck               = new Graphics::TBitmap();
        BmpCheck->Height       = 13;
        BmpCheck->Width        = 13;

        BmpCheck->Canvas->Brush->Color = Color;
        BmpCheck->Canvas->FillRect( BmpCheck->Canvas->ClipRect );

        if( Enabled )
            {
            if(ReadOnly)
                {
                if( Checked )
                    eState = eChkBxDisabledChecked;
                else
                    eState = eChkBxDisabledUnChecked;
                }
            else
                {
                if( Checked )
                    eState = eChkBxChecked;
                else
                    eState = eChkBxUnChecked;
                }
            }
        else
            {
            if( Checked )
                eState = eChkBxDisabledChecked;
            else
                eState = eChkBxDisabledUnChecked;
            }

        BmpCheck->Canvas->Brush->Color  = Color;

        BmpCheck->Canvas->FillRect( Rect( 0, 0, 13, 13 ));
        DrawCheck( eState );
        }

    catch(...)
        {
        }
    }



//////////////////////////////////////
//
// DrawCheck
//
// Fonction: Dessine la coche du CheckBox
//
// P.E.: Etat de la coche
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::DrawCheck( enum StateChkBx eState )
    {
	TColor ColFond;

    if( eState == eChkBxDisabledUnChecked || eState == eChkBxDisabledChecked )
        ColFond = Color;
    else
        ColFond = clWindow;//clBtnHighlight;

    BmpCheck->Canvas->Brush->Color = ColFond;
	BmpCheck->Canvas->Pen->Color   = ColFond;
	BmpCheck->Canvas->FillRect( Rect(0, 0, 13, 13 ));

	BmpCheck->Canvas->Pen->Color   = clBtnShadow;
	BmpCheck->Canvas->MoveTo( 11,   0 );
	BmpCheck->Canvas->LineTo(  0,   0 );
	BmpCheck->Canvas->LineTo(  0,  12 );

	BmpCheck->Canvas->Pen->Color   = clBtnHighlight;
	BmpCheck->Canvas->MoveTo( 12,  0 );
	BmpCheck->Canvas->LineTo( 12, 12 );
	BmpCheck->Canvas->LineTo(  -1, 12 );

	BmpCheck->Canvas->Pen->Color   = clBlack;
	BmpCheck->Canvas->MoveTo( 10,  1 );
	BmpCheck->Canvas->LineTo(  1,  1 );
	BmpCheck->Canvas->LineTo(  1, 11 );

	if( eState == eChkBxDisabledUnChecked || eState == eChkBxDisabledChecked )
		BmpCheck->Canvas->Pen->Color = Color;
	else
		BmpCheck->Canvas->Pen->Color   = cl3DLight;//clBtnFace;
	BmpCheck->Canvas->MoveTo( 11,  1 );
	BmpCheck->Canvas->LineTo( 11,  11 );
	BmpCheck->Canvas->LineTo(  0,  11 );

	if( eState == eChkBxChecked || eState == eChkBxDisabledChecked )
		{
		if( eState == eChkBxDisabledChecked )
			{
			BmpCheck->Canvas->Brush->Color = clBtnShadow;
			BmpCheck->Canvas->Pen->Color   = clBtnShadow;
			}
		else
			{
			BmpCheck->Canvas->Brush->Color = clBlack;
			BmpCheck->Canvas->Pen->Color   = clBlack;
			}
		BmpCheck->Canvas->MoveTo(  3,  5 );
        BmpCheck->Canvas->LineTo(  5,  7 );
        BmpCheck->Canvas->LineTo( 10,  2 );

        BmpCheck->Canvas->MoveTo(  3,  6 );
        BmpCheck->Canvas->LineTo(  5,  8 );
        BmpCheck->Canvas->LineTo( 10,  3 );

        BmpCheck->Canvas->MoveTo(  3,  7 );
        BmpCheck->Canvas->LineTo(  5,  9 );
        BmpCheck->Canvas->LineTo( 10,  4 );
        }
    }



//////////////////////////////////////
//
// InitCaption
//
// Fonction: Cree le caption et l'initialise
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::InitCaption()
    {
	try
        {
        if( LCaption )
            {
            delete LCaption;
            LCaption = NULL;
            }

        LCaption                = new TLabel( this );
		LCaption->Visible       = inherited::Visible;
		LCaption->Parent        = this;
		LCaption->Enabled       = inherited::Enabled;
		LCaption->Font          = Font;
		LCaption->Font->Color   = clBlack;
		LCaption->Caption       = inherited::Caption;
		LCaption->AutoSize      = true;
        LCaption->Top           = ( Height - LCaption->Height ) / 2;
        LCaption->Transparent   = true;
        if( Alignment == eChkBxLeftAlign )
            LCaption->Left      = BmpCheck->Width + SIZE_ESP;
        else
            LCaption->Left      = 0;
        LCaption->OnClick       = CaptionClick;
        LCaption->FocusControl  = this;
        }

    catch(...)
        {
        }
    }


//////////////////////////////////////
//
// CaptionClick
//
// Fonction: Capture le click genere sur le caption et le retourne au controle
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::CaptionClick( TObject *Sender)
	{
	Click();
	}



//////////////////////////////////////
//
// Click
//
// Fonction: Capture Click
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::Click()
	{
	if( !FReadOnly )
		{
		bCheckedFromClick 	= true;
		Checked 			= !Checked;

		if( OnCheck )
			OnCheck( this, Checked );
		inherited::Click();

    if (Enabled)
  		SetFocus();
		}
	}





////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
/*void __fastcall CCheckBox::KeyDown(Word &Key, Classes::TShiftState Shift)
	{
/*	TControl *CtrlLePlusProche 	= NULL;

// NEW 24/01
	if(/*( Key == VK_DOWN ||Key == VK_UP ) && (Shift.Contains(ssShift) || Shift.Contains(ssCtrl)))
/*		{
		CtrlLePlusProche = CEdit::FindControlUpOrDown( Parent, this, Key );
		if( CtrlLePlusProche != NULL )
			::SetFocus( ((TWinControl*)CtrlLePlusProche)->Handle );
		Key = VK_CANCEL;
		}
// END 24/01
	inherited::KeyDown( Key, Shift );*/

//	}




//////////////////////////////////////
//
// KeyPress
//
// Fonction: Capture clavier
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::KeyPress( char &Key )
	{
	if( Key == VK_SPACE )
		Click();
/*	if( Key == VK_SPACE && !FReadOnly )
		Checked = !Checked;*/
	}





//////////////////////////////////////
//
// WndProc
//
// Fonction: Intercepte les evenements
//
// P.E.: Le message
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCheckBox::WndProc( TMessage &Message )
	{
	switch( Message.Msg )
		{
		case WM_SETFOCUS:
			{
			if( !ComponentState.Contains( csDesigning ))
				{
				if( FReadOnly || !TabStop )
					{
					Message.Msg = WM_NULL;
					::SetFocus( GetNextDlgTabItem( Parent->Handle, Handle, false ));
					}
				else
					{
					bFocused = true;
					Repaint();
					}
				}
			else
				{
				bFocused = true;
				Repaint();
				}
			break;
			}

/*		case WM_CREATE:
			{
			if( ComponentState.Contains( csDesigning ))
				{
				Enabled 	= Parent->Enabled;

				if( Parent->ClassNameIs("CGroupBox"))
					ReadOnly 	= ((CGroupBox*)Parent)->ReadOnly;
				}
			break;
			}*/

		case WM_KILLFOCUS:
			{
			bFocused = false;
			Repaint();
			break;
			}

		case WM_ENABLE:
			{
			Enabled = (bool)Message.WParam;
			break;
			}

		case WM_READONLY:
			{
			ReadOnly = (bool)Message.WParam;
			break;
			}

		case BM_GETCHECK:
			{
			if( Checked )
				Message.Result = BST_CHECKED;
			else
				Message.Result = BST_UNCHECKED;
			return;
			}

		case BM_SETCHECK:
			{
			Checked = (bool)Message.WParam;
			break;
			}

		case WM_DESTROY:
			{
/*Mis en commentaire le 28/03/2002 par Anthony*/
  //	if( ComponentState.Contains( csDesigning )&& LCaption )
  //				delete LCaption;
/*Car le LCaption était délété mais réutilisé lors d'un accès dans PAINT
  Ce problème se produit lorsque l'on a un CCheckBox sur un TPageControl et lorsque
  l'on change le style de celui-ci (en flat par exemple)*/
			break;
			}
		}

	inherited::WndProc( Message );
	}


//////////////////////////////////////
//
// GetReference
//
// Fonction:
//
// P.E.: AUCUN
//
// P.S.: Reference
//
//////////////////////////////////////
AnsiString __fastcall CCheckBox::GetReference( void)
{
  return Reference;
}
